//! # 错误处理
//!
//! Kubernetes 相关的错误类型定义和处理。

use thiserror::Error;

/// Kubernetes 错误类型
#[derive(Error, Debug)]
pub enum K8sError {
    #[error("Kubernetes API 错误: {0}")]
    ApiError(#[from] kube::Error),
    
    #[error("配置错误: {0}")]
    ConfigError(String),
    
    #[error("连接错误: {0}")]
    ConnectionError(String),
    
    #[error("服务发现错误: {0}")]
    ServiceDiscoveryError(String),
    
    #[error("资源不存在: {kind}/{name} 在命名空间 {namespace}")]
    ResourceNotFound {
        kind: String,
        name: String,
        namespace: String,
    },
    
    #[error("权限不足: {action} on {resource}")]
    PermissionDenied {
        action: String,
        resource: String,
    },
    
    #[error("序列化错误: {0}")]
    SerializationError(#[from] serde_json::Error),
    
    #[error("YAML 解析错误: {0}")]
    YamlError(#[from] serde_yaml::Error),
    
    #[error("HTTP 请求错误: {0}")]
    HttpError(#[from] reqwest::Error),
    
    #[error("IO 错误: {0}")]
    IoError(#[from] std::io::Error),
    
    #[error("超时错误: {0}")]
    TimeoutError(String),
    
    #[error("健康检查失败: {0}")]
    HealthCheckError(String),
    
    #[error("Operator 错误: {0}")]
    OperatorError(String),
    
    #[error("内部错误: {0}")]
    InternalError(String),
}

/// Kubernetes 结果类型
pub type K8sResult<T> = Result<T, K8sError>;

impl K8sError {
    /// 检查是否为临时错误（可重试）
    pub fn is_temporary(&self) -> bool {
        match self {
            K8sError::ConnectionError(_) |
            K8sError::HttpError(_) |
            K8sError::TimeoutError(_) => true,
            K8sError::ApiError(kube_error) => {
                // 检查 Kubernetes API 错误是否为临时性的
                matches!(kube_error, kube::Error::Api(error_response) 
                    if error_response.code >= 500 && error_response.code < 600)
            }
            _ => false,
        }
    }

    /// 检查是否为权限相关错误
    pub fn is_permission_error(&self) -> bool {
        matches!(self, 
            K8sError::PermissionDenied { .. } 
        ) || matches!(self, K8sError::ApiError(kube::Error::Api(resp)) if resp.code == 403)
    }

    /// 检查是否为资源不存在错误
    pub fn is_not_found_error(&self) -> bool {
        matches!(self,
            K8sError::ResourceNotFound { .. }
        ) || matches!(self, K8sError::ApiError(kube::Error::Api(resp)) if resp.code == 404)
    }

    /// 获取错误代码
    pub fn error_code(&self) -> u16 {
        match self {
            K8sError::ResourceNotFound { .. } => 404,
            K8sError::PermissionDenied { .. } => 403,
            K8sError::ConfigError(_) => 400,
            K8sError::ConnectionError(_) => 503,
            K8sError::TimeoutError(_) => 408,
            K8sError::ApiError(kube::Error::Api(error_response)) => error_response.code,
            _ => 500,
        }
    }

    /// 创建连接错误
    pub fn connection_error(message: impl Into<String>) -> Self {
        K8sError::ConnectionError(message.into())
    }

    /// 创建配置错误
    pub fn config_error(message: impl Into<String>) -> Self {
        K8sError::ConfigError(message.into())
    }

    /// 创建服务发现错误
    pub fn service_discovery_error(message: impl Into<String>) -> Self {
        K8sError::ServiceDiscoveryError(message.into())
    }

    /// 创建资源不存在错误
    pub fn resource_not_found(kind: &str, name: &str, namespace: &str) -> Self {
        K8sError::ResourceNotFound {
            kind: kind.to_string(),
            name: name.to_string(),
            namespace: namespace.to_string(),
        }
    }

    /// 创建权限错误
    pub fn permission_denied(action: &str, resource: &str) -> Self {
        K8sError::PermissionDenied {
            action: action.to_string(),
            resource: resource.to_string(),
        }
    }

    /// 创建超时错误
    pub fn timeout_error(message: impl Into<String>) -> Self {
        K8sError::TimeoutError(message.into())
    }

    /// 创建健康检查错误
    pub fn health_check_error(message: impl Into<String>) -> Self {
        K8sError::HealthCheckError(message.into())
    }
}

// 从 rustcloud-core 错误转换
impl From<rustcloud_core::ServiceError> for K8sError {
    fn from(error: rustcloud_core::ServiceError) -> Self {
        K8sError::InternalError(error.to_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_error_creation() {
        let error = K8sError::config_error("invalid config");
        assert!(matches!(error, K8sError::ConfigError(_)));
        assert_eq!(error.error_code(), 400);
    }

    #[test]
    fn test_resource_not_found() {
        let error = K8sError::resource_not_found("Pod", "my-pod", "default");
        assert!(error.is_not_found_error());
        assert_eq!(error.error_code(), 404);
    }

    #[test]
    fn test_permission_denied() {
        let error = K8sError::permission_denied("create", "pods");
        assert!(error.is_permission_error());
        assert_eq!(error.error_code(), 403);
    }

    #[test]
    fn test_timeout_error() {
        let error = K8sError::timeout_error("connection timeout");
        assert!(error.is_temporary());
        assert_eq!(error.error_code(), 408);
    }
}